//
// modified by Carl Beyer 9/15/09
// renamed to myMatrix.h
// changed the vectors used to a custom Vector class
// added out of range exceptions in the [] operator
// and in the resize function
//
// This is an implementation of a better
// matrix class with bounds checks
//

#ifndef MYMATRIX_H
#define MYMATRIX_H

#include <stdexcept>
#include "myVector.h"

template<typename T>
class Matrix
{
public:
	Matrix(int numRows=1, int numCols=1, const T& initVal=T());
	Vector<T>& operator[](int i);
	const Vector<T>& operator[](int i) const;
	int rows() const;
	int cols() const;
	void resize(int numRows, int numCols);
private:
	int nRows, nCols;
	Vector<Vector<T> > mat;
};

template<typename T>
Matrix<T>::Matrix(int numRows, int numCols, const T& initVal)
: nRows(numRows), nCols(numCols),
	mat(numRows, Vector<T>(numCols,initVal))
{
}

template<typename T>
Vector<T>& Matrix<T>::operator[](int i)
{
	if (i < 0 || nRows <= i)
	{
		throw std::out_of_range("in Matrix<T>::operator[]");
	}
	return mat[i];
}

template<typename T>
const Vector<T>& Matrix<T>::operator[](int i) const
{
	if (i < 0 || nRows <= i)
	{
		throw std::out_of_range("in Matrix<T>::operator[]");
	}
	return mat[i];
}

template<typename T>
int Matrix<T>::rows() const
{
	return nRows;
}

template<typename T>
int Matrix<T>::cols() const
{
	return nCols;
}

template<typename T>
void Matrix<T>::resize(int numRows, int numCols)
{
	if(numRows < 0 || numCols < 0)
		throw std::out_of_range("in Matrix<T>::resize");
	
	mat.resize(numRows);
	for (int i=0; i<numRows; i++)
		mat[i].resize(numCols);

	nRows = numRows;
	nCols = numCols;
}

#endif

